package domain.user;

import java.util.Set;
import java.util.TreeSet;

import junit.framework.Assert;
import junit.framework.TestCase;
import util.HierarchicalSet;

/**
 * also tests invariant after every change.
 */
public class UserTester extends TestCase
{
	protected static final String ID_REGEX = "\\+?[0-9]+" ;
	protected HierarchicalSet<Privilege> emptyHierarchicalSet ;
	protected HierarchicalSet<Privilege> singletonHierarchicalSet ;
	protected HierarchicalSet<Privilege> fullHierarchicalSet ;
	protected Set<Privilege> emptySet ;
	protected Set<Privilege> singletonSet ;
	protected Set<Privilege> fullSet ;

	public UserTester()
	{
		super() ;
		this.emptyHierarchicalSet = new HierarchicalSet<Privilege>() ;
		this.singletonHierarchicalSet = new HierarchicalSet<Privilege>(this.emptyHierarchicalSet,
			Privilege.ADD_THREAD) ;
		this.fullHierarchicalSet = new HierarchicalSet<Privilege>(this.singletonHierarchicalSet, Privilege.ADD_POST) ;
		this.emptySet = this.emptyHierarchicalSet ;
		this.singletonSet = this.singletonHierarchicalSet ;
		this.fullSet = this.fullHierarchicalSet ;
	}

	/**
	 * Test method for {@link domain.user.User#User(long, java.util.Set)}.
	 */
	public void testConstructors()
	{
		final User[] user = new User[6] ;

		user[0] = new User(0, this.emptyHierarchicalSet) ;
		Assert.assertEquals(this.emptyHierarchicalSet, user[0].getPrivileges()) ;
		user[1] = new User(1, this.emptySet) ;
		Assert.assertEquals(this.emptySet, user[1].getPrivileges()) ;

		user[2] = new User(2, this.singletonHierarchicalSet) ;
		Assert.assertEquals(this.singletonHierarchicalSet, user[2].getPrivileges()) ;
		user[3] = new User(3, this.singletonSet) ;
		Assert.assertEquals(this.singletonSet, user[3].getPrivileges()) ;

		user[4] = new User(4, this.fullHierarchicalSet) ;
		Assert.assertEquals(this.fullHierarchicalSet, user[4].getPrivileges()) ;
		user[5] = new User(5, this.fullSet) ;
		Assert.assertEquals(this.fullSet, user[5].getPrivileges()) ;

		/*
		 * test invariant: if all user id's are different,
		 * the size of their set is the size of the array.
		 */
		final Set<Long> set = new TreeSet<Long>() ;
		for (final User element: user)
		{
			set.add(element.getId()) ;
		}
		Assert.assertEquals(user.length, set.size()) ;
	}

	/**
	 * Test method for {@link domain.user.User#equals(java.lang.Object)}.
	 * Test method for {@link domain.user.User#hashCode()}.
	 */
	public void testEqualsAndHashCode()
	{
		final User[] user = { new User(0, this.emptySet), new User(1, this.singletonSet), new User(2, this.fullSet) } ;

		for (int i = 0 ; i < user.length ; i++)
		{
			for (int j = 0 ; j < user.length ; j++)
			{
				if (i == j)
				{
					Assert.assertTrue(user[i].equals(user[j])) ;
					Assert.assertTrue(user[i].hashCode() == user[j].hashCode()) ;
				}
				else
				{
					Assert.assertFalse(user[i].equals(user[j])) ;
				}
			}
		}
	}

	/**
	 * Test method for {@link domain.user.User#addPrivilege(Privilege)}.
	 * Test method for {@link domain.user.User#removePrivilege(Privilege)}.
	 */
	public void testAddRemove()
	{
		final User user = new User(0, this.fullSet) ;
		user.addPrivilege(Privilege.ADD_THREAD) ;
		Assert.assertTrue(user.isAllowed(Privilege.ADD_THREAD)) ;
		user.addPrivilege(Privilege.EDIT_POST) ;
		Assert.assertTrue(user.isAllowed(Privilege.EDIT_POST)) ;
		user.addPrivilege(Privilege.DELETE_POST) ;
		Assert.assertTrue(user.isAllowed(Privilege.DELETE_POST)) ;
		user.removePrivilege(Privilege.ADD_THREAD) ;
		Assert.assertFalse(user.isAllowed(Privilege.ADD_THREAD)) ;
		user.removePrivilege(Privilege.ADD_THREAD) ;
		Assert.assertFalse(user.isAllowed(Privilege.ADD_THREAD)) ;
		user.removePrivilege(Privilege.DENY_PERMISSION) ;
		Assert.assertFalse(user.isAllowed(Privilege.DENY_PERMISSION)) ;
		user.removePrivilege(Privilege.ADD_THREAD) ;
		Assert.assertFalse(user.isAllowed(Privilege.ADD_THREAD)) ;
		user.addPrivilege(Privilege.ADD_THREAD) ;
		Assert.assertTrue(user.isAllowed(Privilege.ADD_THREAD)) ;
	}

}
